<?php
declare(strict_types=1);

namespace app\admin\middleware;

use Closure;
use think\exception\HttpResponseException;
use think\Request;
use think\Response;

class FormTokenCheck
{

    use \app\common\traits\JumpTrait;

    // 定义排除列表（使用键名提高查找性能）
    protected array $exclude = [
        'addon/local'              => true,
        'upload/index'             => true,
        'upload/ueditor_config'    => true,
        'upload_file/file_list'    => true,
        'upload_file/group_list'   => true,
        'upload_file/group_add'    => true,
        'upload_file/group_edit'   => true,
        'upload_file/group_del'    => true,
        'upload_file/move_files'   => true,
        'upload_file/delete_files' => true,
        'login/logout'             => true
    ];

    /**
     * 表单令牌检测
     *
     * @param Request     $request
     * @param Closure     $next
     * @param string|null $token 表单令牌Token名称
     *
     * @return Response
     */
    public function handle(Request $request, Closure $next, string $token = null): Response
    {
        // 跳过参数中包含：no_need__token__==1的请求
        $noNeedToken = (int)($request->post('no_need__token__') ?? 0);
        if ($noNeedToken === 1) {
            return $next($request);
        }

        // 获取当前请求的控制器和方法
        $controller   = $request->controller();
        $action       = $request->action();
        $currentRoute = uncamelize("{$controller}/{$action}");

        // 检查是否在排除列表中（使用 isset 提高查找性能）
        if (isset($this->exclude[$currentRoute])) {
            return $next($request);
        }

        // 执行令牌验证
        $tokenName = $token ?: '__token__';
        if ( ! $request->checkToken($tokenName)) {
            $result = [
                'code' => -1000,
                'msg'  => lang('invalid token'),
                'data' => ['__token__' => $request->buildToken($tokenName)],
                'url'  => '',
                'wait' => 0,
            ];

            throw new HttpResponseException(json($result));
        }

        return $next($request);
    }
}
